private ["_type","_startpoint","_attackpoint","_heliendpoint","_number_vehicles","_parachute_type","_make_jump","_stop_it","_delveccrew"];
if (!isServer) exitWith {diag_log "Reinforcement is server only!"};

_debug = false;

_startpoint = _this select 0;
_attackpoint = _this select 1;
_targetradius = _this select 2;
_heliendpoint = _this select 3;
_number_vehicles = _this select 4;

if (_number_vehicles <= 0) then {_number_vehicles = 1};
if (_number_vehicles > 3) then {_number_vehicles = 3};

if (_debug) then {diag_log Format["(%1)[%2]: %3: %4, %5, %6, %7, %8",diag_tickTime,"createpara3x.sqf","Starting", _startpoint, _attackpoint, _targetradius, _heliendpoint, _number_vehicles];};

if (count _startpoint < 3) exitWith{diag_log Format["(%1)[%2]: %3",diag_tickTime,"createpara3x.sqf","One or more invalid arguments"];};
if (count _attackpoint < 3) exitWith{diag_log Format["(%1)[%2]: %3",diag_tickTime,"createpara3x.sqf","One or more invalid arguments"];};
if (_targetradius <= 0) exitWith{diag_log Format["(%1)[%2]: %3",diag_tickTime,"createpara3x.sqf","One or more invalid arguments"];};
if (count _heliendpoint < 3) exitWith{diag_log Format["(%1)[%2]: %3",diag_tickTime,"createpara3x.sqf","One or more invalid arguments"];};
if (_number_vehicles <=0) exitWith{diag_log Format["(%1)[%2]: %3",diag_tickTime,"createpara3x.sqf","One or more invalid arguments"];};

d_should_be_there = _number_vehicles;

if (isnil "d_c_attacking_grps") then {d_c_attacking_grps = [];};
if (isnil "d_c_reinforcement_grps") then {d_c_reinforcement_grps = [];};

_delveccrew = {
	private ["_crew_vec", "_vehicle", "_time"];
	_crew_vec = _this select 0;
	_vehicle = _this select 1;
	_time = _this select 2;
	sleep _time;
	{if (!isNull _x) then {_x setDamage 1}} forEach _crew_vec;
	sleep 1;
	if (!isNull _vehicle && ({isPlayer _x} count (crew _vehicle)) == 0) then {_vehicle setDamage 1};
};

_make_jump = {
	private ["_vgrp", "_vehicle", "_attackpoint", "_heliendpoint", "_driver_vec", "_wp", "_stop_me", "_parachute_type", "_paragrp", "_unit_array", "_real_units", "_i", "_type", "_one_unit", "_para", "_grp_array","_crew_vec","_delveccrew"];
	_vgrp = _this select 0;
	_vehicle = _this select 1;
	_attackpoint = _this select 2;
	_attackradius = _this select 3;
	_heliendpoint = _this select 4;
	_delveccrew = _this select 5;

	if (_debug) then {diag_log Format["(%1)[%2]: %3: %4, %5, %6, %7, %8, %9",diag_tickTime,"createpara3x.sqf","Make Jump", _vgrp, _vehicle, _attackpoint, _attackradius, _heliendpoint, isnil "_delveccrew"];};
	
	_startpos = position _vehicle;
	_driver_vec = driver _vehicle;
	_crew_vec = crew _vehicle;
	
	_wp = _vgrp addWaypoint [_attackpoint, 0];
	_wp setWaypointBehaviour "CARELESS";
	_wp setWaypointSpeed "NORMAL";
	_wp setwaypointtype "MOVE";
	_wp setWaypointFormation "VEE";
	_wp = _vgrp addWaypoint [_heliendpoint, 0];
	
	_vehicle flyInHeight 100;
	
	sleep 10.0231;
	
	_stop_me = false;
	_checktime = time + 300;
	// While we didn't arrive at destination yet.
	while {_attackpoint distance (leader _vgrp) > 200} do {
		// If the vehicle got destroyed on the way... we remove it from the should_be_there array.
		if (_debug) then {diag_log Format["(%1)[%2]: %3: %4  dist:%5  pos:%6  dam:%7  fuel:%8",diag_tickTime,"createpara3x.sqf","Should be there", d_should_be_there, (_attackpoint distance (leader _vgrp)), getPos _vehicle, damage _vehicle, fuel _vehicle];};
		if (isNull _vehicle || !alive _vehicle || !alive _driver_vec || !canMove _vehicle) exitWith { 
			(d_should_be_there == d_should_be_there - 1);
			if (_debug) then {diag_log Format["(%1)[%2]: %3: veh:%4  alive:%5  alive:%6  canmove:%7",diag_tickTime,"createpara3x.sqf","Vehicle died", isNull _vehicle, alive _vehicle, alive _driver_vec, canMove _vehicle];};
		};
		sleep 0.01;
		// If it took too much time for the vehicle to arrive, we kill it.
		if (time > _checktime) then {
			if (_startpos distance position _vehicle < 500) then {
				if (_debug) then {diag_log Format["(%1)[%2]: %3: dist:%4  time:%5  checktime:%6",diag_tickTime,"createpara3x.sqf","Vehicle too slow", (_startpos distance position _vehicle < 500), time, _checktime];};
				d_should_be_there = d_should_be_there - 1;
				[_crew_vec, _vehicle, 1 + random 1] spawn _delveccrew;
				_stop_me = true;
			} else {
				_checktime = time + 9999999;
			};
		};
		if (_stop_me) exitWith {};
		sleep 2.023;
	};
	if (_debug) then {diag_log Format["(%1)[%2]: %3: veh:%4  alive:%5  alive:%6  canmove:%7  stop:%8",diag_tickTime,"createpara3x.sqf","Vehicle arrived", isNull _vehicle, alive _vehicle, alive _driver_vec, canMove _vehicle, _stop_me];};
	if (_stop_me) exitWith {};
	
	sleep 0.534;
	
	_parachute_type = "ParachuteEast";
	
	// If we reach this test, normally everyone is alive, but we check it for safety :)
	// Otherwise we kill everyone for safety too :)
	if (!isNull _vehicle && alive _vehicle && alive _driver_vec && canMove _vehicle) then {
		if (_debug) then {diag_log Format["(%1)[%2]: %3 (%4) (%5)",diag_tickTime,"createpara3x.sqf","Starting instantiating paras", (["reinforcement_coming",False] call XNetGETJIP),(_vehicle distance _attackpoint)];};
		if (!(["reinforcement_canceled",False] call XNetGETJIP) && (_vehicle distance _attackpoint < 500)) then {
			_cur_radius = _attackradius;
			_paragrp = [d_side_enemy] call x_creategroup;
			_unit_array = ["East","RU","Infantry","RU_InfSquad"] call XfGetConfigGroup;
			_real_units = _unit_array select 0;
			if (_debug) then {diag_log Format["(%1)[%2]: %3: %4, %5, %6",diag_tickTime,"createpara3x.sqf","Creating para", _paragrp, _unit_array,_real_units];};
			_unit_array = nil;
			sleep 0.1;
			for "_i" from 0 to (count _real_units - 1) do {
				_type = _real_units select _i;
				_one_unit = [_type, _paragrp, [10,10,0], 300] call XfCreateUnit;
				// _one_unit = _paragrp createunit [_type, [10,10,0], [], 300,"NONE"];
				_one_unit setVariable ["BIS_noCoreConversations", true];
				_one_unit setSkill (0.7);
				
				_para = createVehicle [_parachute_type, position _vehicle, [], 20, 'NONE'];
				_para setpos [(position _vehicle) select 0,(position _vehicle) select 1,((position _vehicle) select 2)- 10];
				_para setDir random 360;
				_one_unit moveInDriver _para;
				sleep 0.551;
			};
			_paragrp allowFleeing 0;
			_paragrp setCombatMode "RED";
			_paragrp setBehaviour "AWARE";
			
			[_paragrp, _attackpoint, _cur_radius] spawn {
				_grp = _this select 0;
				_pos = _this select 1;
				_rad = _this select 2;
				sleep 20;
				if ((_grp call XfGetAliveUnitsGrp) > 0) then {
					[_grp, _pos, [_pos, _rad], [10, 20, 50]] spawn XMakePatrolWPX;
					_grp setVariable ["D_PATR",true];
				};
			};
			
			d_c_attacking_grps set [count d_c_attacking_grps, _paragrp];
			
			_paragrp spawn {
				private ["_grp"];
				_grp = _this;
				while {alive leader _grp} do {
					// We wait for the current leader to die.
					waituntil { sleep 10; !alive leader _grp; };
					// When the leader is dead, we wait 10 seconds.
					// If no new leader has taken over command, it means that noone is left alive.
					// And thus the while loop will exit, otherwise it comes back in and starts to wait
					// for the new leader to die.
					sleep 10;
				};
				// When we leave the loop, we remove the group from the active attacking groups
				d_c_attacking_grps = d_c_attacking_grps - [_grp];
			};
			
			sleep 0.112;
			d_should_be_there = d_should_be_there - 1;
			
			while {(_heliendpoint distance (leader _vgrp) > 300)} do {
				if (isNull _vehicle || !alive _vehicle || !alive _driver_vec || !canMove _vehicle) exitWith {};
				sleep 5.123;
			};
			
			if (!isNull _vehicle && (_heliendpoint distance _vehicle) > 300) then {
				[_crew_vec, _vehicle, 240 + random 100] spawn _delveccrew;
			} else {
				_vehicle call XfDelVecAndCrew;
			};
			if (!isNull _driver_vec) then {_driver_vec setDamage 1.1};
		};
	} else {
		[_crew_vec, _vehicle, 240 + random 100] spawn _delveccrew;
	};
	if (_debug) then {diag_log Format["(%1)[%2]: %3",diag_tickTime,"createpara3x.sqf","Ending MakeJump"];};
};

_stop_it = false;
if (_debug) then {diag_log Format["(%1)[%2]: %3: %4 (%5)",diag_tickTime,"createpara3x.sqf","Starting the for loop", _number_vehicles,(["reinforcement_coming",False] call XNetGETJIP)];};
for "_i" from 1 to _number_vehicles do {
	if ((["reinforcement_canceled",False] call XNetGETJIP)) exitWith {_stop_it = true};
	_vgrp = [d_side_enemy] call x_creategroup;
	_heli_type = d_transport_chopper call XfRandomArrayVal;
	_spos = [_startpoint select 0, _startpoint select 1, 300];
	_cdir = [_spos, _attackpoint] call XfDirTo;
	_veca = [_spos, _cdir, _heli_type, _vgrp] call XfSpawnVehicle;
	_vehicle = _veca select 0;
	[_vehicle,"Reinforcement"] spawn XfAirMarkerMove;
	if (d_LockAir == 0) then {_vehicle lock true};
	sleep 5.012;
	
	_vehicle flyInHeight 100;
	if (_debug) then {diag_log Format["(%1)[%2]: %3: %4 (%5) %6 %7",diag_tickTime,"createpara3x.sqf","Vehicle instantiated", typeof _vehicle, count crew _vehicle, _vgrp, d_side_enemy];};
	if ((["reinforcement_canceled",False] call XNetGETJIP)) exitWith {_stop_it = true};

	d_c_reinforcement_grps set [count d_c_reinforcement_grps, _vgrp];
	_vgrp spawn {
		private ["_grp"];
		_grp = _this;
		while {alive leader _grp} do {
			// We wait for the current leader to die.
			waituntil { sleep 10; !alive leader _grp; };
			// When the leader is dead, we wait 10 seconds.
			// If no new leader has taken over command, it means that noone is left alive.
			// And thus the while loop will exit, otherwise it comes back in and starts to wait
			// for the new leader to die.
			sleep 10;
		};
		// When we leave the loop, we remove the group from the active reinforcement groups on the way.
		d_c_reinforcement_grps = d_c_reinforcement_grps - [_grp];
	};
	
	[_vgrp,_vehicle,_attackpoint,_targetradius,_heliendpoint, _delveccrew] spawn _make_jump;
	
	sleep 40 + random 30;
};

if (_stop_it) exitWith {};

if (_debug) then {diag_log Format["(%1)[%2]: %3",diag_tickTime,"createpara3x.sqf","Script ended"];};